function v_out = Vcycle_1d(v_in,f_in,nu_down,nu_up,u);
%
%
%

N = length(v_in)-1;
num_levels = log2(N);

ib = zeros(num_levels,1);  % begin index for each level 
ie = zeros(num_levels,1);  % end index for each level

ib(1) = 1; ie(1) = N+1;
len_arr = N+1;
cur_N = N;

for j = 2:num_levels
    cur_N = cur_N/2
    ib(j) = ie(j-1)+1;
    ie(j) = ie(j-1)+(cur_N+1);
    len_arr = len_arr+(cur_N+1);
end

% initialize grid
len_arr

v = zeros(len_arr,1);
f = zeros(len_arr,1);
v(ib(1):ie(1)) = v_in;
f(ib(1):ie(1)) = f_in;

% V-cycle

% traverse down grids

for j = 1:num_levels-1   

    ind_f = ib(j):ie(j);     % fine grid index range 
    ind_c = ib(j+1):ie(j+1); % coarse grid index range

    v(ind_f) = relax(v(ind_f),f(ind_f),nu_down);
    f(ind_c) = restrict(f(ind_f)-apply_operator(v(ind_f)));

end  

if (nargin >= 5) 
   norm(v(ib(1):ie(1))-u)
end

% solve exactly on coarse grid 

h = 1/2; hsq = h*h;
v(ib(num_levels)+1) = (hsq/2)*f(ib(num_levels)+1);

% traverse up grids

for j = num_levels-1:-1:1   

    ind_f = ib(j):ie(j);     % fine grid index range 
    ind_c = ib(j+1):ie(j+1); % coarse grid index range

    v(ind_f) = v(ind_f) + interpolate(v(ind_c));
    v(ind_c) = 0;
    v(ind_f) = relax(v(ind_f),f(ind_f),nu_up);
    
end    

if (nargin >= 5) 
   norm(v(ib(1):ie(1))-u)
end

v_out = v(ib(1):ie(1));
